Skip to content

feat: support oidc discovery in client sdk #652

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from

Conversation

xiaoyijun
Copy link
Contributor

@xiaoyijun xiaoyijun commented Jun 18, 2025

This PR adds comprehensive OpenID Connect (OIDC) Discovery support to the client SDK, implementing the multi-protocol discovery strategy required by the latest MCP draft authorization specification.

🔄 MCP Draft Spec Compliant Discovery Strategy

Implements the exact discovery sequence mandated by the MCP Draft Spec:

  • For Authorization Server URLs with path components:
    • OAuth 2.0 Authorization Server Metadata with path insertion
    • OpenID Connect Discovery with path insertion
    • OpenID Connect Discovery with path appending
  • For Authorization Server URLs without path components:
    • OAuth 2.0 Authorization Server Metadata (/.well-known/oauth-authorization-server)
    • OpenID Connect Discovery (/.well-known/openid-configuration)

✅ Specification Compliance

  • MUST support both OAuth 2.0 and OIDC discovery ✓
  • MUST verify code_challenge_methods_supported in OIDC metadata ✓
  • MUST implement proper path handling for discovery URLs ✓
  • MUST follow the exact discovery priority order ✓

🆕 New Types and Schemas

  • OpenIdProviderMetadataSchema — Full OIDC Discovery 1.0 provider metadata
  • OpenIdProviderDiscoveryMetadataSchema — Hybrid schema for real-world OIDC/OAuth2 mixed responses
  • AuthorizationServerMetadata — Union type supporting both OAuth 2.0 and OIDC metadata
  • Enhanced OAuthTokensSchema — With optional id_token field for OIDC compatibility

🔧 New Discovery Functions

  • discoverAuthorizationServerMetadata() — Main entry point implementing the draft spec’s discovery chain
  • Path-aware discovery with exact URL patterns per specification
  • Enhanced error handling with CORS retry logic and graceful 404 handling

⚡ Enhanced Authorization Flow

  • Support for OIDC offline_access scope with automatic prompt=consent
  • id_token handling in token responses
  • Full backward compatibility with legacy MCP servers

Motivation and Context

This change implements the latest MCP draft authorization specification requirements at https://modelcontextprotocol.io/specification/draft/basic/authorization, ensuring the SDK is compliant with the evolving MCP standard.

  • Significantly improves compatibility with modern identity providers (Keycloak, Auth0, Logto, etc.) that primarily use OIDC discovery
  • Maintains complete backward compatibility

How Has This Been Tested?

Unit tests have been added and updated, and all of them passed.

Breaking Changes

None. This change is fully backward-compatible:

  • Existing discoverOAuthMetadata() function preserved (marked deprecated)
  • Legacy MCP server behavior maintained as final fallback
  • All existing OAuth 2.0 functionality unchanged

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Documentation update

Checklist

  • I have read the MCP Documentation
  • My code follows the repository's style guidelines
  • New and existing tests pass locally
  • I have added appropriate error handling
  • I have added or updated documentation as needed

@xiaoyijun
Copy link
Contributor Author

Hi @pcarleton , thanks for the heads-up on the spec change! I've now implemented the corresponding OIDC discovery support in the SDK. Would you mind taking a look when you get a chance? Thanks~

@xiaoyijun xiaoyijun force-pushed the feat-support-oidc-discovery-in-client-sdk branch from 0b3f1bc to cf64a97 Compare June 18, 2025 03:48
@dsp-ant
Copy link
Member

dsp-ant commented Jun 18, 2025

@ihrpr please hold merging this until we make a final decision if i want to actually have the #677 in the spec

@ihrpr ihrpr linked an issue Jun 18, 2025 that may be closed by this pull request
Copy link
Member

@dsp-ant dsp-ant left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OICD and OAuth 2.0 AS metadata are no the same. They share a common base. We need to represent this in the type system appropriately so that clients can distinguish what to call.

This implement should have a common base interface that an OAuthMetadataSchema and an OICDMetadataSchema that inherit from it and discoverOAuthMetadata should return a Promise<OAuthMetadataSchema | OICDMetadataSchema | undefined>, that clients can discriminate on or downcast to the AuthserverBaseSchema.

Comment on lines 540 to 554
const fetchWithCorsFallback = async (url: URL, protocolVersion: string) => {
try {
return await fetch(url, {
headers: {
"MCP-Protocol-Version": protocolVersion
}
})
} catch (error) {
if (error instanceof TypeError) {
// CORS errors come back as TypeError, try again without protocol version header
return await fetch(url);
}
throw error;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be an async function fetchWithCorsFallback() and not const fetchWithCorsFallback =, to stay in line with everything else here and ensure that we define a proper return type.

Comment on lines 291 to 297
/**
* The `OAuthMetadataSchema` is compatible with both OIDC and OAuth2
* discovery responses. Because OIDC's metadata is a superset, `zod` will
* correctly parse the fields defined in our schema and simply ignore any
* additional OIDC-specific fields.
*/
return OAuthMetadataSchema.parse(await response.json());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OICD is not a superset. They have a common base, but they do have both fields that they dont share, AS Metadata has introspection_endpoint, revocation_endpoint, introspection_endpoint_auth_methods_supported and OICD has userinfo_endpoint, subject_types_supported, id_token_signing_alg_values_supported for example.

@pcarleton
Copy link
Contributor

tried adding more explicit typing here: main...feat-support-oidc-discovery-in-client-sdk

@xiaoyijun
Copy link
Contributor Author

Hi @dsp-ant , thank you so much for the detailed review.
I will wait for the spec in modelcontextprotocol/modelcontextprotocol#677 (now it's modelcontextprotocol/modelcontextprotocol#797) to be finalized. Once it's merged, I'll update this PR to implement your suggestions.

@xiaoyijun
Copy link
Contributor Author

Hi @pcarleton , thanks for your input and for highlighting the relevant code. Feel free to push directly to this branch if you'd like to collaborate on the changes. No worries if not, I'm happy to handle the refactoring myself once the spec is ready.
Thanks!

@panva
Copy link

panva commented Jun 24, 2025

@dsp-ant in response to the following comments:

OIDC and OAuth 2.0 AS metadata are not the same. They share a common base. We need to represent this in the type system appropriately so that clients can distinguish what to call.

They have a common base, but they do have both fields that they dont share, AS Metadata has introspection_endpoint, revocation_endpoint, introspection_endpoint_auth_methods_supported and OICD has userinfo_endpoint, subject_types_supported, id_token_signing_alg_values_supported for example.

The history of how Discovery 1.0 and RFC8414 came to be appears to give their nuance some credibility but at the end of the day they infact describe one and the same entity.

Both Discovery 1.0 and RFC8414 responses for the same issuer identifier describe the same Authorization Server, when resolved from a given issuer identifier they ought to return the same metadata.

  • In Discovery 1.0 > "Additional OpenID Provider Metadata parameters MAY also be used.".
  • In RFC8414 > "Additional authorization server metadata parameters MAY also be used. Some are defined by other specifications, such as OpenID Connect Discovery 1.0".
  • Both Discovery 1.0 and RFC8414 register metadata in the same IANA "OAuth Authorization Server Metadata" registry.

As a Client module developer my expectation is that I am able to resolve an issuer identifier to the two respective well-known URLs this issuer may host its AS metadata at and race to successful completion of either one.

Not having these endpoints return the same response when both are supported by the issuer has lead to client race conditions wrt. missing metadata in the past.

Therefore, the only typings related thing that may differ is the optionality of some of the properties, but not the properties themselves. They may (and in fact often do) all appear in both endpoints' responses.

@xiaoyijun xiaoyijun force-pushed the feat-support-oidc-discovery-in-client-sdk branch from cf64a97 to a3fe322 Compare July 19, 2025 16:35
@xiaoyijun xiaoyijun requested review from a team as code owners July 19, 2025 16:35
@xiaoyijun xiaoyijun requested review from pcarleton and ihrpr July 19, 2025 16:35
@xiaoyijun xiaoyijun force-pushed the feat-support-oidc-discovery-in-client-sdk branch from a3fe322 to 2de25f0 Compare July 19, 2025 17:01
@xiaoyijun xiaoyijun force-pushed the feat-support-oidc-discovery-in-client-sdk branch 2 times, most recently from e0b4ffe to bcbaa86 Compare July 19, 2025 17:30
@xiaoyijun xiaoyijun force-pushed the feat-support-oidc-discovery-in-client-sdk branch from bcbaa86 to c148ef1 Compare July 19, 2025 17:31
@xiaoyijun xiaoyijun requested a review from dsp-ant July 20, 2025 00:38
@xiaoyijun
Copy link
Contributor Author

Hi @dsp-ant @pcarleton @ihrpr , I hope you're all doing well.

The OIDC discovery spec has been merged into the draft authorization specification, and I've now fully implemented the OpenID Connect Discovery support as required by the latest MCP draft authorization specification.

When you have a moment, I'd appreciate your review. Thanks! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

enhance auth server discovery with OAuth2 and OIDC metadata support
5 participants